//
//  stmtkind.h
//  LTLBMC
//
//  Created by GD Huang on 5/17/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#ifndef LTLBMC_stmtkind_h
#define LTLBMC_stmtkind_h

#include "instr.h"
#include "exp.h"
#include "location.h"
#include "astVisitor.h"

namespace cilast {
    
    
    
    class stmt;
    class block;
    
    class instr;
    
    class Instr;
    class Return;
    class Goto;
    class Break;
    class Continue;
    class If;
    class Switch;
    class Loop;
    class Block;
    class TryFinally;
    class TryExcept;
    
    
    class stmtkind : public OCamlObject {
        
    public:    
        stmtkind();
        virtual int accept(astVisitor*);
        
        
    };
    
    class Instr : public stmtkind {
    public:    
        std::vector<instr*> minstrs;
        
        int accept(astVisitor*);
    };
    
    class Return : public stmtkind {
    public:    
        exp* mexp;
        location* mlocation;
        
        int accept(astVisitor*);
    };
    
    class Goto : public stmtkind {
    public:    
        stmt* mstmt;
        location* mlocation;
        
        int accept(astVisitor*);
    };
    
    class Break : public stmtkind {
    public:    
        location* mlocation;
        
        int accept(astVisitor*);
    };
    
    class Continue : public stmtkind {
    public:    
        location* mlocation;
        
        int accept(astVisitor*);
    };
    
    class If : public stmtkind {
    public:    
        exp* mexp;
        block* mthenBlock;
        block* melseBlock;
        location* mlocation;
        
        int accept(astVisitor*);
    };
    
    class Switch : public stmtkind {
    public:    
        exp* mexp;
        block* mblock;
        std::vector<stmt*> mstmts;
        location* mlocation;
        
        int accept(astVisitor*);
    };
    
    class Loop : public stmtkind {
    public:    
        block* mblock;
        location* mlocation;
        stmt* mcontinueStmt;
        stmt* mbreakStmt;
        
        int accept(astVisitor*);
    };
    
    class Block : public stmtkind {
    public:    
        block* mblock;
        
        int accept(astVisitor*);
    };
    
    class TryFinally : public stmtkind {
    public:
        int accept(astVisitor*);
    };
    
    class TryExcept : public stmtkind {
    public:
        int accept(astVisitor*);
    };
    
}

#endif
